package com.zyf.project.binaryproto.encoder.impl.fixed;

import com.zyf.project.binaryproto.converter.FixedValueConverter;
import com.zyf.project.binaryproto.encoder.impl.FixedArrayFieldEncoder;
import com.zyf.project.binaryproto.specification.BinarySliceSpecification;
import com.zyf.project.binaryproto.specification.FieldSpecification;
import org.jetbrains.annotations.NotNull;
import utils.binary.BytesSlices;
import utils.binary.impl.BytesSlice;
import utils.binary.io.BytesOutputBuffer;
import utils.io.NumberMask;

import java.lang.reflect.Method;

/**
 * <h1>静态字符数组编码器</h1>
 * <p>继承了 {@link FixedArrayFieldEncoder}</p>
 *
 * @author Zhou Yifan
 */
public class FixedCharArrayFieldEncoder extends FixedArrayFieldEncoder {

    private static final char[] EMPTY_ARRAY = {};

    public FixedCharArrayFieldEncoder(
            BinarySliceSpecification binarySliceSpecification,
            FieldSpecification fieldSpecification,
            Method reader,
            FixedValueConverter valueConverter) {
        super(binarySliceSpecification, fieldSpecification, reader, valueConverter);
    }

    /**
     * 对数组类型的值进行固定长度的编码；
     *
     * @param values 待编码数组
     * @param buffer 目标缓存
     * @return 写入的字节数
     */
    protected int encodeArray(Object values, BytesOutputBuffer buffer) {
        char[] valueArray = values == null ? EMPTY_ARRAY : (char[]) values;

        int count = valueArray.length;

        int counterSize = NumberMask.NORMAL.getMaskLength(count);
        int elementSize = sliceSpecification.getLength();

        int size = counterSize + elementSize * count;
        byte[] outbuff = new byte[size];
        NumberMask.NORMAL.writeMask(count, outbuff, 0);

        for (int i = 0; i < count; i++) {
            valueConverter.encode(valueArray[i], outbuff, counterSize + elementSize * i);
        }

        buffer.write(outbuff);
        return size;
    }

    @Override
    public char[] decodeField(@NotNull BytesSlices fieldBytes) {
        char[] values = new char[fieldBytes.getCount()];
        BytesSlice itemSlice;
        for (int i = 0; i < values.length; i++) {
            itemSlice = fieldBytes.getDataSlice(i);
            if (itemSlice.getSize() == 0) {
                values[i] = (char) valueConverter.getDefaultValue();
            } else {
                values[i] = (char) valueConverter.decode(itemSlice);
            }
        }
        return values;
    }
}
